﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Threading;

namespace Puzzle
{
    public partial class GamePage : PhoneApplicationPage
    {
        Button[,] botoes = new Button[4, 4];
        Timer tm;
        DateTime inicio;

        public GamePage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
            Random rdn = new Random();
            var contador = 0;
            while (true)
            {
                if (MatrizEstaComplete())
                    break;

                int linha, coluna;
                linha = rdn.Next(4);
                coluna = rdn.Next(4);
                if (linha == 3 && coluna == 3)
                    continue;
                if (botoes[linha, coluna] == null)
                {
                    var botao = ((LayoutRoot.Children[1] as StackPanel).Children[0] as Grid).Children.ElementAt(contador) as Button;
                    botao.Click += btnClick_MoveButton;
                    botao.SetValue(Grid.ColumnProperty, coluna);
                    botao.SetValue(Grid.RowProperty, linha);
                    botoes[linha, coluna] = botao;
                    contador++;
                }
            }

            #region Inicia montado
            //for (int i = 0; i < 15; i++)
            //{
            //    var botao = ((LayoutRoot.Children[1] as StackPanel).Children[0] as Grid).Children.ElementAt(i) as Button;
            //    botao.Click += btnClick_MoveButton;
            //} 
            #endregion
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //Iniciando o Timer, contador de tempo do jogo
            inicio = DateTime.Now;
            tm = new Timer(TimerCallBack, null, 0, 1000);
        }

        private void TimerCallBack(object sender)
        {
            var tempoPassado = DateTime.Now.Subtract(inicio);
            Action a = new Action(() => lblTempo.Text = string.Format("{0:00}:{1:00}", tempoPassado.Minutes, tempoPassado.Seconds));
            lblTempo.Dispatcher.BeginInvoke(a);
        }

        private void btnClick_MoveButton(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            var posicaoBotao = new Posicao
            {
                Coluna = Convert.ToInt32(btn.GetValue(Grid.ColumnProperty)),
                Linha = Convert.ToInt32(btn.GetValue(Grid.RowProperty))
            };
            var posicaoAlvo = PosicaoVazia();
            if (PodeSeMover(posicaoBotao, posicaoAlvo))
            {
                btn.SetValue(Grid.ColumnProperty, posicaoAlvo.Coluna);
                btn.SetValue(Grid.RowProperty, posicaoAlvo.Linha);
                if (Finalizou())
                {
                    tm.Dispose();
                    NavigationService.Navigate(new Uri(string.Format("/EndGamePage.xaml?time={0}",lblTempo.Text), UriKind.RelativeOrAbsolute));
                }
            }
        }

        private bool PodeSeMover(Posicao posicaoBotao, Posicao posicaoAlvo)
        {
            List<Posicao> todasPosicoes = new List<Posicao>();
            List<Posicao> posicoesPossiveis = new List<Posicao>();
            todasPosicoes.Add(new Posicao { Coluna = posicaoAlvo.Coluna + 1, Linha = posicaoAlvo.Linha });
            todasPosicoes.Add(new Posicao { Coluna = posicaoAlvo.Coluna - 1, Linha = posicaoAlvo.Linha });
            todasPosicoes.Add(new Posicao { Coluna = posicaoAlvo.Coluna, Linha = posicaoAlvo.Linha + 1 });
            todasPosicoes.Add(new Posicao { Coluna = posicaoAlvo.Coluna, Linha = posicaoAlvo.Linha - 1 });

            foreach (var item in todasPosicoes)
            {
                if (!(item.Coluna > 3 || item.Coluna < 0 || item.Linha > 3 || item.Linha < 0))
                    posicoesPossiveis.Add(item);
            }

            return posicoesPossiveis.Contains(posicaoBotao);
        }

        private bool MatrizEstaComplete()
        {
            var qntNulos = 0;
            foreach (var item in botoes)
            {
                if (item == null)
                    qntNulos++;
            }
            return !(qntNulos > 1);
        }

        private Posicao PosicaoVazia()
        {
            var inteiros = new List<string>(new[] 
            { 
                "0,0","0,1","0,2","0,3",
                "1,0","1,1","1,2","1,3",
                "2,0","2,1","2,2","2,3",
                "3,0","3,1","3,2","3,3" 
            });
            foreach (var item in ((LayoutRoot.Children[1] as StackPanel).Children[0] as Grid).Children)
            {
                var posicao = string.Format("{0},{1}", item.GetValue(Grid.RowProperty), (item.GetValue(Grid.ColumnProperty)));
                inteiros.Remove(posicao);
            }

            return new Posicao { Linha = int.Parse(inteiros[0].Split(',')[0]), Coluna = int.Parse(inteiros[0].Split(',')[1]) };
        }

        private bool Finalizou()
        {
            var grid = ((LayoutRoot.Children[1] as StackPanel).Children[0] as Grid).Children;
            var j = 2;
            for (int i = 0; i < grid.Count; i++)
            {
                var item = grid[i];
                
                try
                {
                    var btn = item as Button;
                    var numeroBotao = int.Parse(btn.Name.Replace("btn", ""));
                    if (numeroBotao == 5)
                        j = 3;
                    else if (numeroBotao == 9)
                        j = 4;
                    else if (numeroBotao == 13)
                        j = 5;
                    var btnLinha = (int)btn.GetValue(Grid.RowProperty) + 1;
                    var btnColuna = (int)btn.GetValue(Grid.ColumnProperty) + 1;
                    if ((btnLinha + btnColuna) != j)
                        return false;
                }
                catch
                {
                    return false;
                }
                j++;
            }
            return ((int)btn15.GetValue(Grid.RowProperty) == 3 && (int)btn15.GetValue(Grid.ColumnProperty) == 2);
        }

        public class Posicao
        {
            public int Linha { get; set; }
            public int Coluna { get; set; }

            public override bool Equals(object obj)
            {
                var obj2 = obj as Posicao;
                return this.Coluna == obj2.Coluna && this.Linha == obj2.Linha;
            }
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            tm.Dispose();
            NavigationService.Navigate(new Uri(string.Format("/WinPage.xaml?time={0}", lblTempo.Text), UriKind.RelativeOrAbsolute));
        }

    }
}